﻿using HaoCoding.DCdb.General.Threading;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;

namespace HaoCoding.DCdb.WaterfallTree
{
    /// <summary>
    /// W树型类
    /// </summary>
    public partial class WTree : IDisposable
    {
        /// <summary>
        /// 计数器
        /// </summary>
        private readonly Countdown WorkingFallCount = new Countdown();

        /// <summary>
        /// 是否被回收
        /// </summary>
        private volatile bool disposed = false;
        /// <summary>
        /// 是否被关闭
        /// </summary>
        private volatile bool Shutdown = false;

        private readonly Scheme scheme;

        /// <summary>
        /// 数据堆
        /// </summary>
        public readonly IHeap heap;

        /// <summary>
        /// 实例化
        /// </summary>
        /// <param name="heap">数据堆</param>
        public WTree(IHeap heap)
        {
            if (heap == null)
                throw new NullReferenceException("heap");

            this.heap = heap;
        }

        #region Locator

        /// <summary>
        /// 获取所有的定位数据
        /// </summary>
        /// <returns></returns>
        protected IEnumerable<Locator> GetAllLocators()
        {
            return scheme.Select(kv => kv.Value);
        }

        #endregion

        #region Cache

        /// <summary>
        /// 缓存线程
        /// </summary>
        private Thread CacheThread;

        #endregion

        #region IDisposable Members

        /// <summary>
        /// 垃圾回收
        /// </summary>
        /// <param name="disposing">是否执行回收操作</param>
        private void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    Shutdown = true;
                    if (CacheThread != null)
                        CacheThread.Join();  //调用线程挂起，等待被调用线程执行完毕后，继续执行。被调用线程执行Join方法，告诉调用线程，你先暂停，我执行完了，你再执行。从而保证了先后关系。

                    WorkingFallCount.Wait();

                    heap.Close();
                }

                disposed = true;
            }
        }

        /// <summary>
        /// 手动垃圾回收
        /// </summary>
        public void Dispose()
        {
            Dispose(true);

            GC.SuppressFinalize(this);  //告诉垃圾回收器不要调用当前对象的Dispose方法，因为之前Dispose(true);已经做过了
        }

        /// <summary>
        /// 析构函数
        /// </summary>
        ~WTree()
        {
            Dispose(false);
        }

        /// <summary>
        /// 手动关闭
        /// </summary>
        public virtual void Close()
        {
            Dispose();
        }

        #endregion
    }
}
